Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


meshchatx/src/backend/bot_handler.py 8bb38d3e516cac4240b15bd3cc881d1e55daacbb (8bb38d3e) Text, 10.93 KB

Tff7b72import T7ee787json
Tff7b72import T7ee787logging
Tff7b72import T7ee787os
Tff7b72import T7ee787shutil
Tff7b72import T7ee787subprocess
Tff7b72import T7ee787sys
Tff7b72import T7ee787time
Tff7b72import T7ee787uuid

Tff7b72import T7ee787RNS

Te6edf3logger Tff7b72= Te6edf3loggingTff7b72.Td2a8ffgetLoggerTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.botsTa5d6ff"Tb4b4b4)


Tff7b72class T56d364BotHandlerTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3identity_pathTb4b4b4, Te6edf3config_managerTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffidentity_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3identity_pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffconfig_manager Tff7b72= Te6edf3config_manager
Tff7b72selfTff7b72.Td2a8ffbots_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffidentity_pathTb4b4b4, Ta5d6ff"Ta5d6ffbotsTa5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbots_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrunning_bots Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ffstate_file Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbots_dirTb4b4b4, Ta5d6ff"Ta5d6ffbots_state.jsonTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ff_load_stateTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrunner_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(
Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffdirnameTb4b4b4(Tff7b72__file__Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffbot_process.pyTa5d6ff"Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8ff_load_stateTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstate_fileTb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffbots_state Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadTb4b4b4(Te6edf3fTb4b4b4)
T8b949e# Ensure all storage paths are absolute
Tff7b72for Te6edf3entry Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Tff7b72if Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff" Tff7b72in Te6edf3entryTb4b4b4:
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72except Tf85149FileNotFoundErrorTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffbots_state Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffbots_state Tff7b72= Tb4b4b4[Tb4b4b4]

Tff7b72def Td2a8ff_save_stateTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstate_fileTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4, Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3jsonTff7b72.Td2a8ffdumpTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4, Te6edf3fTb4b4b4, Te6edf3indentTff7b72=T79c0ff2Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass

Tff7b72def Td2a8ffget_available_templatesTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4[
Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffechoTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffEcho BotTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffRepeats any message it receives.Ta5d6ff"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffnoteTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffNote BotTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffStore and retrieve notes using JSON storage.Ta5d6ff"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffreminderTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffReminder BotTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffSet and receive reminders using SQLite storage.Ta5d6ff"Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4]

Tff7b72def Td2a8ffrestore_enabled_botsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3entry Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffenabledTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstart_botTb4b4b4(
Te6edf3template_idTff7b72=Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6fftemplate_idTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3nameTff7b72=Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3bot_idTff7b72=Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3storage_dirTff7b72=Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffwarningTb4b4b4(Ta5d6ff"Ta5d6ffFailed to restore bot Tffd700%sTa5d6ff: Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3excTb4b4b4)

Tff7b72def Td2a8ffget_statusTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3botsTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]

Tff7b72for Te6edf3entry Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Te6edf3bot_id Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4)
Te6edf3template Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftemplate_idTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftemplateTa5d6ff"Tb4b4b4)
Te6edf3name Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ffUnknownTa5d6ff"
Te6edf3pid Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4)

Te6edf3running Tff7b72= Tff7b72False
Tff7b72if Te6edf3bot_id Tff7b72in Tff7b72selfTff7b72.Td2a8ffrunning_botsTb4b4b4:
Te6edf3running Tff7b72= Tff7b72True
Tff7b72elif Te6edf3pidTb4b4b4:
Te6edf3running Tff7b72= Tff7b72selfTff7b72.Td2a8ff_is_pid_aliveTb4b4b4(Te6edf3pidTb4b4b4)

Te6edf3address_pretty Tff7b72= Tff7b72None
Te6edf3address_full Tff7b72= Tff7b72None

T8b949e# Try running instance first
Te6edf3instance Tff7b72= Tff7b72selfTff7b72.Td2a8ffrunning_botsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3bot_idTb4b4b4, Tb4b4b4{Tb4b4b4}Tb4b4b4)Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffinstanceTa5d6ff"Tb4b4b4)
Tff7b72if Tb4b4b4(
Te6edf3instance
Tff7b72and Tffa657getattrTb4b4b4(Te6edf3instanceTb4b4b4, Ta5d6ff"Ta5d6ffbotTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72and Tffa657getattrTb4b4b4(Te6edf3instanceTff7b72.Td2a8ffbotTb4b4b4, Ta5d6ff"Ta5d6fflocalTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3address_pretty Tff7b72= Te6edf3RNSTff7b72.Td2a8ffprettyhexrepTb4b4b4(Te6edf3instanceTff7b72.Td2a8ffbotTff7b72.Td2a8fflocalTff7b72.Td2a8ffhashTb4b4b4)
Te6edf3address_full Tff7b72= Te6edf3RNSTff7b72.Td2a8ffhexrepTb4b4b4(Te6edf3instanceTff7b72.Td2a8ffbotTff7b72.Td2a8fflocalTff7b72.Td2a8ffhashTb4b4b4, Te6edf3delimitTff7b72=Tff7b72FalseTb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass

T8b949e# Fallback to identity file on disk
Tff7b72if Te6edf3address_full Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3identity Tff7b72= Tff7b72selfTff7b72.Td2a8ff_load_identity_for_botTb4b4b4(Te6edf3bot_idTb4b4b4)
Tff7b72if Te6edf3identityTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3destination Tff7b72= Te6edf3RNSTff7b72.Td2a8ffDestinationTb4b4b4(Te6edf3identityTb4b4b4, Ta5d6ff"Ta5d6fflxmfTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffdeliveryTa5d6ff"Tb4b4b4)
Te6edf3address_full Tff7b72= Te6edf3destinationTff7b72.Td2a8ffhashTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4)
Te6edf3address_pretty Tff7b72= Te6edf3RNSTff7b72.Td2a8ffprettyhexrepTb4b4b4(Te6edf3destinationTff7b72.Td2a8ffhashTb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass

Te6edf3botsTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Te6edf3bot_idTb4b4b4,
Ta5d6ff"Ta5d6fftemplateTa5d6ff"Tb4b4b4: Te6edf3templateTb4b4b4,
Ta5d6ff"Ta5d6fftemplate_idTa5d6ff"Tb4b4b4: Te6edf3templateTb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3nameTb4b4b4,
Ta5d6ff"Ta5d6ffaddressTa5d6ff"Tb4b4b4: Te6edf3address_pretty Tff7b72or Ta5d6ff"Ta5d6ffUnknownTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fffull_addressTa5d6ff"Tb4b4b4: Te6edf3address_fullTb4b4b4,
Ta5d6ff"Ta5d6ffrunningTa5d6ff"Tb4b4b4: Te6edf3runningTb4b4b4,
Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4: Te6edf3pidTb4b4b4,
Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4: Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffhas_lxmfyTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4,
Ta5d6ff"Ta5d6ffdetection_errorTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffrunning_botsTa5d6ff"Tb4b4b4: Tb4b4b4[Te6edf3b Tff7b72for Te6edf3b Tff7b72in Te6edf3bots Tff7b72if Te6edf3bTb4b4b4[Ta5d6ff"Ta5d6ffrunningTa5d6ff"Tb4b4b4]Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffbotsTa5d6ff"Tb4b4b4: Te6edf3botsTb4b4b4,
Tb4b4b4}

Tff7b72def Td2a8ffstart_botTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3template_idTb4b4b4, Te6edf3nameTff7b72=Tff7b72NoneTb4b4b4, Te6edf3bot_idTff7b72=Tff7b72NoneTb4b4b4, Te6edf3storage_dirTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e# Reuse existing entry or create new
Te6edf3entry Tff7b72= Tff7b72None
Tff7b72if Te6edf3bot_idTb4b4b4:
Tff7b72for Te6edf3e Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Tff7b72if Te6edf3eTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bot_idTb4b4b4:
Te6edf3entry Tff7b72= Te6edf3e
Tff7b72break
Tff7b72if Te6edf3entry Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3bot_id Tff7b72= Te6edf3bot_id Tff7b72or Te6edf3uuidTff7b72.Td2a8ffuuid4Tb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffhex
Te6edf3bot_storage_dir Tff7b72= Te6edf3storage_dir Tff7b72or Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbots_dirTb4b4b4, Te6edf3bot_idTb4b4b4)
Te6edf3bot_storage_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffabspathTb4b4b4(Te6edf3bot_storage_dirTb4b4b4)
Te6edf3entry Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Te6edf3bot_idTb4b4b4,
Ta5d6ff"Ta5d6fftemplate_idTa5d6ff"Tb4b4b4: Te6edf3template_idTb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3name Tff7b72or Ta5d6fffTa5d6ff"Tffd700{Te6edf3template_idTff7b72.Td2a8fftitleTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff BotTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4: Te6edf3bot_storage_dirTb4b4b4,
Ta5d6ff"Ta5d6ffenabledTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4,
Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ffbots_stateTff7b72.Td2a8ffappendTb4b4b4(Te6edf3entryTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3bot_storage_dir Tff7b72= Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4]
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6fftemplate_idTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3template_id
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3name Tff7b72or Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6fffTa5d6ff"Tffd700{Te6edf3template_idTff7b72.Td2a8fftitleTb4b4b4(Tb4b4b4)Tffd700}Ta5d6ff BotTa5d6ff"
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffenabledTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72True

Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3bot_storage_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)

Te6edf3cmd Tff7b72= Tb4b4b4[
Te6edf3sysTff7b72.Td2a8ffexecutableTb4b4b4,
Tff7b72selfTff7b72.Td2a8ffrunner_pathTb4b4b4,
Ta5d6ff"Ta5d6ff--templateTa5d6ff"Tb4b4b4,
Te6edf3template_idTb4b4b4,
Ta5d6ff"Ta5d6ff--nameTa5d6ff"Tb4b4b4,
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ff--storageTa5d6ff"Tb4b4b4,
Te6edf3bot_storage_dirTb4b4b4,
Tb4b4b4]

Te6edf3proc Tff7b72= Te6edf3subprocessTff7b72.Td2a8ffPopenTb4b4b4(Te6edf3cmdTb4b4b4, Te6edf3cwdTff7b72=Te6edf3bot_storage_dirTb4b4b4) T8b949e# noqa: S603
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3procTff7b72.Td2a8ffpid
Tff7b72selfTff7b72.Td2a8ff_save_stateTb4b4b4(Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffrunning_botsTb4b4b4[Te6edf3bot_idTb4b4b4] Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffinstanceTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffthreadTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffstop_eventTa5d6ff"Tb4b4b4: Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6fftemplateTa5d6ff"Tb4b4b4: Te6edf3template_idTb4b4b4,
Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4: Te6edf3procTff7b72.Td2a8ffpidTb4b4b4,
Tb4b4b4}
Te6edf3loggerTff7b72.Td2a8ffinfoTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffStarted bot Tffd700{Te6edf3bot_idTffd700}Ta5d6ff (template: Tffd700{Te6edf3template_idTffd700}Ta5d6ff) pid=Tffd700{Te6edf3procTff7b72.Td2a8ffpidTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3bot_id

Tff7b72def Td2a8ffstop_botTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bot_idTb4b4b4)Tb4b4b4:
Te6edf3entry Tff7b72= Tff7b72None
Tff7b72for Te6edf3e Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Tff7b72if Te6edf3eTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bot_idTb4b4b4:
Te6edf3entry Tff7b72= Te6edf3e
Tff7b72break
Tff7b72if Te6edf3entry Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72False

Te6edf3pid Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3pidTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72if Te6edf3sysTff7b72.Td2a8ffplatformTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ffwinTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3subprocessTff7b72.Td2a8ffrunTb4b4b4(
Tb4b4b4[Ta5d6ff"Ta5d6fftaskkillTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/PIDTa5d6ff"Tb4b4b4, Tffa657strTb4b4b4(Te6edf3pidTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ff/TTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff/FTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3checkTff7b72=Tff7b72FalseTb4b4b4,
Te6edf3timeoutTff7b72=T79c0ff5Tb4b4b4,
Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3osTff7b72.Td2a8ffkillTb4b4b4(Te6edf3pidTb4b4b4, T79c0ff15Tb4b4b4)
T8b949e# brief wait
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.5Tb4b4b4)
T8b949e# optional force kill if still alive
Tff7b72tryTb4b4b4:
Te6edf3osTff7b72.Td2a8ffkillTb4b4b4(Te6edf3pidTb4b4b4, T79c0ff0Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffkillTb4b4b4(Te6edf3pidTb4b4b4, T79c0ff9Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72pass
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffwarningTb4b4b4(
Ta5d6ff"Ta5d6ffFailed to terminate bot Tffd700%sTa5d6ff pid Tffd700%sTa5d6ff: Tffd700%sTa5d6ff"Tb4b4b4,
Te6edf3bot_idTb4b4b4,
Te6edf3pidTb4b4b4,
Te6edf3excTb4b4b4,
Tb4b4b4)

Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffpidTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72None
Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffenabledTa5d6ff"Tb4b4b4] Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ff_save_stateTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3bot_id Tff7b72in Tff7b72selfTff7b72.Td2a8ffrunning_botsTb4b4b4:
Tff7b72del Tff7b72selfTff7b72.Td2a8ffrunning_botsTb4b4b4[Te6edf3bot_idTb4b4b4]
Te6edf3loggerTff7b72.Td2a8ffinfoTb4b4b4(Ta5d6ff"Ta5d6ffStopped bot Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3bot_idTb4b4b4)
Tff7b72return Tff7b72True

Tff7b72def Td2a8ffrestart_botTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bot_idTb4b4b4)Tb4b4b4:
Te6edf3entry Tff7b72= Tff7b72None
Tff7b72for Te6edf3e Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Tff7b72if Te6edf3eTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bot_idTb4b4b4:
Te6edf3entry Tff7b72= Te6edf3e
Tff7b72break
Tff7b72if Te6edf3entry Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffUnknown bot: Tffd700{Te6edf3bot_idTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffstop_botTb4b4b4(Te6edf3bot_idTb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ffstart_botTb4b4b4(
Te6edf3template_idTff7b72=Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6fftemplate_idTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3nameTff7b72=Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]Tb4b4b4,
Te6edf3bot_idTff7b72=Te6edf3bot_idTb4b4b4,
Te6edf3storage_dirTff7b72=Te6edf3entryTb4b4b4[Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8ffdelete_botTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bot_idTb4b4b4)Tb4b4b4:
T8b949e# Stop it first
Tff7b72selfTff7b72.Td2a8ffstop_botTb4b4b4(Te6edf3bot_idTb4b4b4)

T8b949e# Remove from state
Te6edf3entry Tff7b72= Tff7b72None
Tff7b72for Te6edf3iTb4b4b4, Te6edf3e Tff7b72in Tffa657enumerateTb4b4b4(Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3eTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bot_idTb4b4b4:
Te6edf3entry Tff7b72= Te6edf3e
Tff7b72del Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4[Te6edf3iTb4b4b4]
Tff7b72break

Tff7b72if Te6edf3entryTb4b4b4:
T8b949e# Delete storage dir
Te6edf3storage_dir Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3storage_dir Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3storage_dirTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Te6edf3storage_dirTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3loggerTff7b72.Td2a8ffwarningTb4b4b4(
Ta5d6ff"Ta5d6ffFailed to delete storage dir for bot Tffd700%sTa5d6ff: Tffd700%sTa5d6ff"Tb4b4b4,
Te6edf3bot_idTb4b4b4,
Te6edf3excTb4b4b4,
Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ff_save_stateTb4b4b4(Tb4b4b4)
Te6edf3loggerTff7b72.Td2a8ffinfoTb4b4b4(Ta5d6ff"Ta5d6ffDeleted bot Tffd700%sTa5d6ff"Tb4b4b4, Te6edf3bot_idTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72return Tff7b72False

Tff7b72def Td2a8ffget_bot_identity_pathTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bot_idTb4b4b4)Tb4b4b4:
Te6edf3entry Tff7b72= Tff7b72None
Tff7b72for Te6edf3e Tff7b72in Tff7b72selfTff7b72.Td2a8ffbots_stateTb4b4b4:
Tff7b72if Te6edf3eTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3bot_idTb4b4b4:
Te6edf3entry Tff7b72= Te6edf3e
Tff7b72break

Tff7b72if Tff7b72not Te6edf3entryTb4b4b4:
Tff7b72return Tff7b72None

Te6edf3storage_dir Tff7b72= Te6edf3entryTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstorage_dirTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3storage_dirTb4b4b4:
Tff7b72return Tff7b72None

T8b949e# LXMFy stores identity in the 'config' subdirectory by default
Te6edf3id_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_dirTb4b4b4, Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3id_pathTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3id_path

T8b949e# Fallback to direct identity file if it was moved or configured differently
Te6edf3id_path_alt Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_dirTb4b4b4, Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3id_path_altTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3id_path_alt

T8b949e# LXMFy may nest inside config/lxmf
Te6edf3id_path_lxmf Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storage_dirTb4b4b4, Ta5d6ff"Ta5d6ffconfigTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fflxmfTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3id_path_lxmfTb4b4b4)Tb4b4b4:
Tff7b72return Te6edf3id_path_lxmf

Tff7b72return Tff7b72None

Tff7b72def Td2a8ff_load_identity_for_botTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3bot_idTb4b4b4)Tb4b4b4:
Te6edf3identity_path Tff7b72= Tff7b72selfTff7b72.Td2a8ffget_bot_identity_pathTb4b4b4(Te6edf3bot_idTb4b4b4)
Tff7b72if Tff7b72not Te6edf3identity_pathTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72tryTb4b4b4:
Tff7b72return Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8fffrom_fileTb4b4b4(Te6edf3identity_pathTb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Tff7b72None

Tf0883e@staticmethod
Tff7b72def Td2a8ff_is_pid_aliveTb4b4b4(Te6edf3pidTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Te6edf3pidTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72tryTb4b4b4:
Te6edf3osTff7b72.Td2a8ffkillTb4b4b4(Te6edf3pidTb4b4b4, T79c0ff0Tb4b4b4)
Tff7b72return Tff7b72True
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72return Tff7b72False

Tff7b72def Td2a8ffstop_allTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72for Te6edf3bot_id Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ffrunning_botsTff7b72.Td2a8ffkeysTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstop_botTb4b4b4(Te6edf3bot_idTb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────